package net.zf.base;

import io.micrometer.observation.ObservationRegistry;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.DefaultChatClient;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.chat.client.observation.ChatClientObservationConvention;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.ChatOptions;
import org.springframework.ai.template.TemplateRenderer;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

public class ZFChatClientBuilder implements ChatClient.Builder {

    protected final ZFChatClient.DefaultChatClientRequestSpec defaultRequest;

    public ZFChatClientBuilder(ChatModel chatModel) {
        this(chatModel, ObservationRegistry.NOOP, (ChatClientObservationConvention)null);
    }

    public ZFChatClientBuilder(ChatModel chatModel, ObservationRegistry observationRegistry, @Nullable ChatClientObservationConvention customObservationConvention) {
        Assert.notNull(chatModel, "the " + ChatModel.class.getName() + " must be non-null");
        Assert.notNull(observationRegistry, "the " + ObservationRegistry.class.getName() + " must be non-null");
        this.defaultRequest = new ZFChatClient.DefaultChatClientRequestSpec(chatModel, (String)null, Map.of(), (String)null, Map.of(), List.of(), List.of(), List.of(), List.of(), (ChatOptions)null, List.of(), Map.of(), observationRegistry, customObservationConvention, Map.of(), (TemplateRenderer)null);
    }

    public ChatClient build() {
        return new ZFChatClient(this.defaultRequest);
    }

    public ChatClient.Builder clone() {
        return this.defaultRequest.mutate();
    }

    public ChatClient.Builder defaultAdvisors(Advisor... advisors) {
        this.defaultRequest.advisors(advisors);
        return this;
    }

    public ChatClient.Builder defaultAdvisors(Consumer<ChatClient.AdvisorSpec> advisorSpecConsumer) {
        this.defaultRequest.advisors(advisorSpecConsumer);
        return this;
    }

    public ChatClient.Builder defaultAdvisors(List<Advisor> advisors) {
        this.defaultRequest.advisors(advisors);
        return this;
    }

    public ChatClient.Builder defaultOptions(ChatOptions chatOptions) {
        this.defaultRequest.options(chatOptions);
        return this;
    }

    public ChatClient.Builder defaultUser(String text) {
        this.defaultRequest.user(text);
        return this;
    }

    public ChatClient.Builder defaultUser(Resource text, Charset charset) {
        Assert.notNull(text, "text cannot be null");
        Assert.notNull(charset, "charset cannot be null");

        try {
            this.defaultRequest.user(text.getContentAsString(charset));
            return this;
        } catch (IOException var4) {
            throw new RuntimeException(var4);
        }
    }

    public ChatClient.Builder defaultUser(Resource text) {
        return this.defaultUser(text, Charset.defaultCharset());
    }

    public ChatClient.Builder defaultUser(Consumer<ChatClient.PromptUserSpec> userSpecConsumer) {
        this.defaultRequest.user(userSpecConsumer);
        return this;
    }

    public ChatClient.Builder defaultSystem(String text) {
        this.defaultRequest.system(text);
        return this;
    }

    public ChatClient.Builder defaultSystem(Resource text, Charset charset) {
        Assert.notNull(text, "text cannot be null");
        Assert.notNull(charset, "charset cannot be null");

        try {
            this.defaultRequest.system(text.getContentAsString(charset));
            return this;
        } catch (IOException var4) {
            throw new RuntimeException(var4);
        }
    }

    public ChatClient.Builder defaultSystem(Resource text) {
        return this.defaultSystem(text, Charset.defaultCharset());
    }

    public ChatClient.Builder defaultSystem(Consumer<ChatClient.PromptSystemSpec> systemSpecConsumer) {
        this.defaultRequest.system(systemSpecConsumer);
        return this;
    }

    public ChatClient.Builder defaultToolNames(String... toolNames) {
        this.defaultRequest.toolNames(toolNames);
        return this;
    }

    public ChatClient.Builder defaultToolCallbacks(ToolCallback... toolCallbacks) {
        this.defaultRequest.toolCallbacks(toolCallbacks);
        return this;
    }

    public ChatClient.Builder defaultToolCallbacks(List<ToolCallback> toolCallbacks) {
        this.defaultRequest.toolCallbacks(toolCallbacks);
        return this;
    }

    public ChatClient.Builder defaultTools(Object... toolObjects) {
        this.defaultRequest.tools(toolObjects);
        return this;
    }

    public ChatClient.Builder defaultToolCallbacks(ToolCallbackProvider... toolCallbackProviders) {
        this.defaultRequest.toolCallbacks(toolCallbackProviders);
        return this;
    }

    public ChatClient.Builder defaultToolContext(Map<String, Object> toolContext) {
        this.defaultRequest.toolContext(toolContext);
        return this;
    }

    public ChatClient.Builder defaultTemplateRenderer(TemplateRenderer templateRenderer) {
        Assert.notNull(templateRenderer, "templateRenderer cannot be null");
        this.defaultRequest.templateRenderer(templateRenderer);
        return this;
    }

    void addMessages(List<Message> messages) {
        this.defaultRequest.messages(messages);
    }
}
